Swfit-06.指针(UnsafePointer)

Swift中也有专门的指针类型,这些都被定性为“Unsafe”(不安全的)。
常见的有以下4种类型:
  • UnsafePointer<Pointee>类似于 const Pointee *
  • UnsafeMutablePointer<Pointee> 类似于 Pointee *
  • UnsafeRawPointer 类似于 const void *
  • UnsafeMutableRawPointer 类似于 void *
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    var age = 10
    func test1(_ ptr: UnsafeMutablePointer<Int>) {
    ptr.pointee += 10
    }
    func test2(_ ptr: UnsafePointer<Int>) {
    print(ptr.pointee)
    }
    test1(&age)
    test2(&age) // 20
    print(age) // 20

    var age = 10
    func test3(_ ptr: UnsafeMutableRawPointer) {
    ptr.storeBytes(of: 20, as: Int.self)
    }
    func test4(_ ptr: UnsafeRawPointer) {
    print(ptr.load(as: Int.self))
    }
    test3(&age)
    test4(&age) // 20
    print(age) // 20
  • 获得指向某个变量的指针:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var age = 11
    var ptr1 = withUnsafeMutablePointer(to: &age) { $0 }
    var ptr2 = withUnsafePointer(to: &age) { $0 }
    ptr1.pointee = 22
    print(ptr2.pointee) // 22
    print(age) // 22

    var ptr3 = withUnsafeMutablePointer(to: &age) { UnsafeMutableRawPointer($0) }
    var ptr4 = withUnsafePointer(to: &age) { UnsafeRawPointer($0) }
    ptr3.storeBytes(of: 33, as: Int.self)
    print(ptr4.load(as: Int.self)) // 33
    print(age) // 33
  • 获得指向堆空间实例的指针:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // UnsafeRawPointer(bitPattern:)函数用来生成指向某一地址的指针
    var ptr = UnsafeRawPointer(bitPattern: 0x100001234)

    class Person {}
    // 类似于 *p = person
    var person = Person()
    // p = &person, p是person变量的地址值
    var ptr = withUnsafePointer(to: &person) { UnsafeRawPointer($0) }
    // ptr.load(as: UInt.self) 类似于 *p, 取出地址中存储的值,也就是Person实例在堆上的地址值
    var heapPtr = UnsafeRawPointer(bitPattern: ptr.load(as: UInt.self))
    print(heapPtr!)
  • 创建指针:

    • 非泛型

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
        	// 创建
      var ptr = malloc(16)
      // 存
      ptr?.storeBytes(of: 11, as: Int.self)
      ptr?.storeBytes(of: 22, toByteOffset: 8, as: Int.self)
      // 取
      print((ptr?.load(as: Int.self))!) // 11
      // fromByteOffset: 地址偏移
      print((ptr?.load(fromByteOffset: 8, as: Int.self))!) // 22
      // 销毁
      free(ptr)

      var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
      ptr.storeBytes(of: 11, as: Int.self)
      // advanced: 也是地址偏移
      ptr.advanced(by: 8).storeBytes(of: 22, as: Int.self)
      print(ptr.load(as: Int.self)) // 11
      print(ptr.advanced(by: 8).load(as: Int.self)) // 22
      // 销毁
      ptr.deallocate()
    • 泛型
      基础数据类型:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
        var ptr = UnsafeMutablePointer<Int>.allocate(capacity: 3) 
      ptr.initialize(to: 11)
      // successor()后继, 表示向后走<Int>长度个字节
      ptr.successor().initialize(to: 22)
      ptr.successor().successor().initialize(to: 33)
      print(ptr.pointee) // 11
      // 这里的 + 指的是指针的加,步长为<Int>长度个字节
      print((ptr + 1).pointee) // 22
      print((ptr + 2).pointee) // 33

      print(ptr[0]) // 11
      print(ptr[1]) // 22
      print(ptr[2]) // 33
      ptr.deinitialize(count: 3)
      ptr.deallocate()

      对象类型:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
        	class Person {
      var age: Int
      var name: String
      init(age: Int, name: String) {
      self.age = age
      self.name = name
      }
      deinit { print(name, "deinit") }
      }
      var ptr = UnsafeMutablePointer<Person>.allocate(capacity: 3)
      ptr.initialize(to: Person(age: 10, name: "Jack"))
      (ptr + 1).initialize(to: Person(age: 11, name: "Rose"))
      (ptr + 2).initialize(to: Person(age: 12, name: "Kate"))
      // Jack deinit
      // Rose deinit
      // Kate deinit
      ptr.deinitialize(count: 3)
      ptr.deallocate()
  • 指针之间的转换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
      	var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1) 
    ptr.assumingMemoryBound(to: Int.self).pointee = 11
    (ptr + 8).assumingMemoryBound(to: Double.self).pointee = 22.0

    // 只改变类型,而不改变其值
    //(值指的是二进制数据,也就是你告诉计算机这是什么类型,计算机就按什么类型解读这些二进制数据)
    print(unsafeBitCast(ptr, to: UnsafePointer<Int>.self).pointee) // 11
    print(unsafeBitCast(ptr + 8, to: UnsafePointer<Double>.self).pointee) // 22.0
    ptr.deallocate()

    // unsafeBitCast是忽略数据类型的强制转换,不会因为数据类型的变化而改变原来的内存数据
    // 类似于C++中的reinterpret_cast

    class Person {}
    var person = Person()
    var ptr = unsafeBitCast(person, to: UnsafeRawPointer.self)
    print(ptr)
  • 关于指针的强制类型转换可参考这篇

Share